package com.zh.test.controller;

import com.zh.test.ProxyAndAspect.StaticProxyTestImpl;
import com.zh.test.Thread.ThreadPool;
import com.zh.test.bean.*;
import com.zh.test.exception.ErrorEnum;
import com.zh.test.exception.NotFoundInventoryException;
import com.zh.test.service.testMapper;
import com.zh.test.util.springUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RequestMapping("/test")
@RestController
public class testController {
    Logger logger = LoggerFactory.getLogger(testController.class);
    @Autowired
    StaticProxyTestImpl proxyTest;
    //    @Autowired
//    testServiceImpl testService;
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    ThreadPool threadPool;
    @Autowired
    testMapper testMapper;

    @Value("${test.freedom:freedom-0}")
    public String FREEDOM;

    /**
     * @describe 测试切面
     * @author zh
     * @date 2021/9/6 10:34
     * @param
     * @return void
     */
    @AspectLogs(AspectLog = "这是test1", AspectEnums = AspectEnums.TEST1)
    @GetMapping(value = "/test1")
    public void test1(@RequestParam String name) {
        System.out.print("hello,world" + name);
        List<Map<String, Object>> maps = jdbcTemplate.queryForList(name);
        logger.info(maps.toString());
        //todo 通过外部重写 配置文件的参数 ,可以做到<根据环境随意更改配置信息> ,更高级的就是在脚本中自动识别环境,做到<不同环境不同参数>,自由度超级高,
        // 前提是配置文件中要提前写好 配置项.
        // 此处有三层配置,第一 默认配置  ,第二 配置文件配置  ,第三 命令行启动参数配置,第一配置兜底,第三配置自由度高
        logger.info(FREEDOM);
    }


    @AspectLogs(AspectLog = "这是test2", AspectEnums = AspectEnums.TEST2)
    @GetMapping(value = "/test2")
    public OutJson test2(@RequestParam Integer i) {
        OutJson out = new OutJson();
        out.setCode(200).setMessage("success");
        return out;
    }
    /**
     * @describe 测试跳转
     * @author zh
     * @date 2021/9/6 10:33
     * @param
     * @return void
     */
    @GetMapping(value = "/test3")
    public void test3(HttpServletRequest request, HttpServletResponse response, @RequestParam String name) {

        logger.info("name:{}", name);
        try {
            response.sendRedirect("../../../../html/hello.html");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping(value = "/test4", method = RequestMethod.POST)
    public void test4(Person p) {
        logger.info("用户信息{}", p.toString());
    }

    @AspectLogs(AspectLog = "这是test5的方法执行", AspectEnums = AspectEnums.TEST2)
    @RequestMapping(value = "/test5", method = RequestMethod.GET)
    public void test5(HttpServletRequest request, @RequestParam(value = "name") String name) {
        proxyTest.show();

    }

    @AspectLogs(AspectLog = "通过Spring钩子异步过去bean实例,同时证明spring中bean实例是默认单例模式")
    @RequestMapping(value = "/test6", method = RequestMethod.GET)
    public void test6(HttpServletRequest request, @RequestParam(value = "name") String name) {
        StaticProxyTestImpl tt = springUtils.getBean(StaticProxyTestImpl.class);
        tt.show();
        StaticProxyTestImpl ttt = springUtils.getBean(StaticProxyTestImpl.class);
        ttt.show(3);
        System.out.print(name);

    }

    @AspectLogs(AspectLog = "这是测试i++  ++i", AspectEnums = AspectEnums.TEST1)
    @RequestMapping(value = "/test7", method = RequestMethod.GET)
    public void test7(HttpServletRequest request, @RequestParam(value = "name") String name) {
        /**
         * i =i++   i值复制到栈顶,i自增1 ,栈顶原值赋值回i =1
         * i++   i值复制到栈顶,i自增1 ,栈顶原值未赋值回,所以i =2
         * j = i++  i值复制到栈顶 ,i自增1,  栈顶值赋值给j 所以  i=2 j=1
         * i = ++i  i值自增1 ,i值复制到栈顶,栈顶值赋值回i 所以i=2
         * i++  i值自增1  所以i=2
         * j= i++  i值自增1,i值复制到栈顶,栈顶值赋值给j  所以 i=2  j=2
         * */
        int i = 1;
        int j = 1;
        int m = 1;
        int n = 1;
        int y = 1;
        int t = 1;
        y++;
        ++t;
        i = i++;
        int e = j++;
        m = ++m;
        int b = ++n;

        for (int c = 1; c < 10; c = c++) {
            System.out.print(c);
        }

    }

    @AspectLogs(AspectLog = "这是测试异步获取bean实例", AspectEnums = AspectEnums.TEST1)
    @RequestMapping(value = "/test8", method = RequestMethod.GET)
    public void test8(HttpServletRequest request, @RequestParam(value = "name") String name) {
       /* p.toString();

        Person p2=  springUtil2.getBean(Person.class);
        if(p == p2){
            System.out.print("定义同类型的变量,当指向同一个堆实例时,物理内存中相同的,虽然在栈的操作变量栈中有两个变量,但是这两个变量指向了同一个堆实例");
        }*/
    }

    @AspectLogs(AspectLog = "这是测试yml自定义属性以及注入,spring默认使用无参的构造函数去创建bean实例,然后对bean实例赋值,所以需要set/get方法,spring自动注入的过程等同于人工new对象赋值", AspectEnums = AspectEnums.TEST1)
    @RequestMapping(value = "/test9", method = RequestMethod.GET)
    public void test9(HttpServletRequest request, @RequestParam(required = false, value = "name") String name) {
        YmlBean y = springUtils.getBean(YmlBean.class);
        YmlBean2 y2 = springUtils.getBean(YmlBean2.class);
        Person p = springUtils.getBean(Person.class);
    }

    /**
     * 多层对象的spirng接参  被requestbody注解的对象,可以直接接受来自请求的参数,作用与map同样
     */
    @RequestMapping(value = "/test10", method = RequestMethod.POST)
    public void test10(@RequestBody Activity activity) {
        int i = 0;
    }

    /**
     *
     */
    @RequestMapping(value = "/test11", method = RequestMethod.GET)
    public void test11() {
        // todo https://www.cnblogs.com/aeolian/p/9228907.html
        // todo jdbctemplate 是对  原生jdbc 的高级封装, 对其每个步骤都提供了接口的方式执行,方便开发者自定义实现方式
        /*执行增删改  返回值为增删改的行数
        int update = jdbcTemplate.update();
         */
        /*执行查询 返回查询结果,jdbctemplate对接口参数进行了内设封装,可以直接使用,开发者可自实现封装方法
        jdbcTemplate.query()
         */
        /*执行其他非增删改查的sql ,比如新建表,添加索引,更改数据库等,参数为接口,开发者可调用jdbctemplate预设实现,或者自实现方法
        jdbcTemplate.execute();
        */

        //testService.test1();

        List<Map<String, Object>> maps = testMapper.test1();
        maps.stream().forEach(m -> {
            m.forEach((k, v) -> {
                System.out.println(k + " : " + v);
            });
        });

    }

    @RequestMapping(value = "/test12", method = RequestMethod.POST)
    public void test12(@RequestBody HashMap<String, String> m) {
        System.out.println(m);

    }

    /**
     * @return
     * @Author zh
     * @Description 证明线程池中的存活着不同的线程
     * @Param
     **/
    @GetMapping("/test13")
    public void test13() {
        threadPool.test1();
        threadPool.test2();
        threadPool.test3();
        System.out.println(Thread.currentThread().getName());
    }

    /**
     * @return
     * @Author zh
     * @Description 测试通过ControllerAdvice捕获异常
     * @Date 2020/10/15
     * @Param
     **/
    @GetMapping("/test14")
    public OutJson test14() throws NotFoundInventoryException {
        throw new NotFoundInventoryException(ErrorEnum.ERROR);

    }

    /**
     * @return
     * @Author zh
     * @Description 测试通过ControllerAdvice捕获异常
     * @Date 2020/10/15
     * @Param
     **/
    @GetMapping("/test15")
    public OutJson test15() throws Exception {
        throw new Exception();

    }

    @GetMapping("/test16")
    public void test16() {

        System.out.println("===============================================");
        //Object[] objects = Stream.of("2", "3", "4").filter(x -> testMapper.test2(x).get("operator").equals("lisi")).toArray();
        Object[] objects1 = Stream.of("2", "3", "4").map(x -> testMapper.test2(x)).filter(m -> m.get("operator").equals("lisi")).toArray();
        System.out.println(Stream.of(objects1).collect(Collectors.toList()));

    }

    /**
     * @return
     * @Author zh
     * @Description 测试多层复合对象做mybatis参数的语法
     * @Date 2020/10/15
     * @Param
     **/
    @GetMapping("/test17")
    public void test17() {

        InnerBean i = new InnerBean().setId("2");
        InnerBean ii = new InnerBean().setId("2").setResourceId("0001");
        OuterBean o = new OuterBean().setInnerBean(i);
        OuterBean oo = new OuterBean().setInnerBean(ii);
        Map<String, Object> stringObjectMap = testMapper.test3(o);


        List<Map<String, Object>> stringObjectMap1 = testMapper.test4(oo);
        System.out.println(stringObjectMap1);
    }


}
